﻿using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Linq.Expressions;
using fastCSharp.code.cSharp;
using System.Reflection;

namespace fastCSharp.sql.cache.whole.events
{
    /// <summary>
    /// 事件缓存
    /// </summary>
    /// <typeparam name="valueType">表格类型</typeparam>
    /// <typeparam name="modelType">模型类型</typeparam>
    public abstract class cache<valueType, modelType> : copy<valueType, modelType>
        where valueType : class, modelType
        where modelType : class
    {
        /// <summary>
        /// 数据集合
        /// </summary>
        public abstract IEnumerable<valueType> Values { get; }
        /// <summary>
        /// 添加记录事件
        /// </summary>
        public event Action<valueType> OnInserted;
        /// <summary>
        /// 添加记录
        /// </summary>
        /// <param name="value">新添加的对象</param>
        [MethodImpl((MethodImplOptions)fastCSharp.pub.MethodImplOptionsAggressiveInlining)]
        protected void callOnInserted(valueType value)
        {
            if (OnInserted != null) OnInserted(value);
        }
        /// <summary>
        /// 更新记录事件
        /// </summary>
        public event Action<valueType, valueType, valueType, fastCSharp.code.memberMap<modelType>> OnUpdated;
        /// <summary>
        /// 更新记录
        /// </summary>
        /// <param name="cacheValue"></param>
        /// <param name="value">更新后的对象</param>
        /// <param name="oldValue">更新前的对象</param>
        [MethodImpl((MethodImplOptions)fastCSharp.pub.MethodImplOptionsAggressiveInlining)]
        protected void callOnUpdated(valueType cacheValue, valueType value, valueType oldValue, fastCSharp.code.memberMap<modelType> memberMap)
        {
            if (OnUpdated != null) OnUpdated(cacheValue, value, oldValue, memberMap);
        }
        /// <summary>
        /// 删除记录事件
        /// </summary>
        public event Action<valueType> OnDeleted;
        /// <summary>
        /// 删除记录
        /// </summary>
        /// <param name="value">被删除的对象</param>
        [MethodImpl((MethodImplOptions)fastCSharp.pub.MethodImplOptionsAggressiveInlining)]
        protected void callOnDeleted(valueType value)
        {
            if (OnDeleted != null) OnDeleted(value);
        }
        /// <summary>
        /// SQL操作缓存
        /// </summary>
        /// <param name="sqlTool">SQL操作工具</param>
        /// <param name="group">数据分组</param>
        protected cache(fastCSharp.emit.sqlTable.sqlTool<valueType, modelType> sqlTool, int group) : base(sqlTool, group) { }
        /// <summary>
        /// 获取所有缓存数据
        /// </summary>
        /// <returns></returns>
        public IEnumerable<valueType> getAllValue()
        {
            return Values;
        }
        /// <summary>
        /// 获取日志流
        /// </summary>
        /// <param name="memberCount">成员加载计数器</param>
        /// <returns></returns>
        public fastCSharp.sql.logStream<valueType, modelType> GetLogStream(fastCSharp.sql.logStream.memberCount memberCount = null, bool isMemberMap = true)
        {
            return new fastCSharp.sql.logStream<valueType, modelType>(this, memberCount, isMemberMap);
        }
        /// <summary>
        /// 获取日志流
        /// </summary>
        /// <param name="memberCount">成员加载计数器</param>
        /// <returns></returns>
        public fastCSharp.sql.logStream<valueType, modelType>.where GetLogStream(Func<modelType, bool> isValue, fastCSharp.sql.logStream.memberCount memberCount = null, bool isMemberMap = true)
        {
            return new fastCSharp.sql.logStream<valueType, modelType>.where(this, memberCount, isMemberMap, isValue);
        }
    }
    /// <summary>
    /// 事件缓存
    /// </summary>
    /// <typeparam name="valueType">表格类型</typeparam>
    /// <typeparam name="modelType">模型类型</typeparam>
    public abstract class cache<valueType, modelType, memberCacheType> : cache<valueType, modelType>
        where valueType : class, modelType
        where modelType : class
        where memberCacheType : class
    {
        /// <summary>
        /// 获取所有缓存数据
        /// </summary>
        public readonly Func<IEnumerable<valueType>> GetAllValue;
        /// <summary>
        /// 获取成员缓存
        /// </summary>
        public readonly Func<valueType, memberCacheType> GetMemberCache;
        /// <summary>
        /// 设置成员缓存
        /// </summary>
        private Action<valueType, memberCacheType> setMemberCache;
        /// <summary>
        /// 设置成员缓存数据
        /// </summary>
        private Action<memberCacheType, valueType> setMemberCacheValue;
        /// <summary>
        /// 获取所有成员缓存
        /// </summary>
        public readonly Func<IEnumerable<memberCacheType>> GetAllMemberCache;
        /// <summary>
        /// SQL操作缓存
        /// </summary>
        /// <param name="sqlTool">SQL操作工具</param>
        /// <param name="group">数据分组</param>
        protected cache(fastCSharp.emit.sqlTable.sqlTool<valueType, modelType> sqlTool, Expression<Func<valueType, memberCacheType>> memberCache, int group)
            : base(sqlTool, group)
        {
            if (group == 0)
            {
                if (memberCache == null)
                {
                    if (typeof(valueType) != typeof(memberCacheType)) log.Default.Throw(log.exceptionType.Null);
                    GetAllValue = getAllValue;
                }
                else
                {
                    if (fastCSharp.emit.constructor<memberCacheType>.New == null) log.Default.Throw("找不到无参构造函数 " + typeof(memberCacheType).FullName, null, false);
                    memberExpression<valueType, memberCacheType> expression = new memberExpression<valueType, memberCacheType>(memberCache);
                    if (expression.Field == null) log.Error.Throw(log.exceptionType.ErrorOperation);
                    GetMemberCache = expression.GetMember;
                    setMemberCache = expression.SetMember;
                    GetAllMemberCache = getAllMemberCache;
                    setMemberCacheValue = fastCSharp.emit.pub.UnsafeSetField<memberCacheType, valueType>("Value");
                }
            }
        }
        /// <summary>
        /// 设置成员缓存与数据
        /// </summary>
        [MethodImpl((MethodImplOptions)fastCSharp.pub.MethodImplOptionsAggressiveInlining)]
        protected void setMemberCacheAndValue(valueType value)
        {
            if (setMemberCache != null)
            {
                if (setMemberCacheValue == null) setMemberCache(value, fastCSharp.emit.constructor<memberCacheType>.New());
                else
                {
                    memberCacheType memberCache = fastCSharp.emit.constructor<memberCacheType>.New();
                    setMemberCache(value, memberCache);
                    setMemberCacheValue(memberCache, value);
                }
            }
        }
        /// <summary>
        /// 所有成员缓存
        /// </summary>
        private IEnumerable<memberCacheType> getAllMemberCache()
        {
            foreach (valueType value in Values)
            {
                yield return GetMemberCache(value);
            }
        }
    }
}
